#include <cfa/cfa.h>
#include <cfa/expr.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <deque>
#include <set>
#include <map>

using namespace std;

struct ptr_compare {
	bool operator() (const Node* a, const Node* b){
		return a<b;
	}
};

struct str_compare
{
	bool operator()(const char* x, const char* y){
		return strcmp(x,y) < 0;
	}
};
int main(int argc, const char **argv)
{
  vector<Expr*> vv;
  freopen(NULL, "w", stdout);
  vector<CFA*> vCFA;
  getCFA(vCFA, vv, argc, argv);
  deque<Node*> todo;
  map<const char*, CFA*, str_compare> mCFA;
  for(unsigned i=0;i<vCFA.size();i++){
  	mCFA.insert ( pair<const char*,CFA*>(vCFA[i]->GetId(), vCFA[i]) );
  }
  printf("Function name<-> CFA map is constructed.\n");
  set<Node*, ptr_compare> visited;
  todo.push_back(mCFA["main"]->GetInitNode());
  visited.insert(mCFA["main"]->GetInitNode());
  mCFA["main"]->PrintCFA();
  int c=0;
  while(!todo.empty()){
	Node* n =todo.front();
	todo.pop_front();
	c++;

	if(isBinNode(n)){
		printf("Binary Node %p with Prop. ", n);
		PrintProp(getProp(n));
		printf(", TNode %pi, and FNode %p.\n", getTNode(n), getFNode(n));
		if(visited.find(getTNode(n))==visited.end()){
			todo.push_back(getTNode(n));
			visited.insert(getTNode(n));
		}
		if(visited.find(getFNode(n))==visited.end()){
			todo.push_back(getFNode(n));
			visited.insert(getFNode(n));
		}
	}else if(isAssignNode(n)){
		printf("Assign Node %p with NextNode %p and operation ", n, getNext(n));
		PrintExpr(getLval(n));
		printf("=");
		PrintExpr(getRval(n));
		printf("\n");
		if(visited.find(getNext(n))==visited.end()){
			todo.push_back(getNext(n));
			visited.insert(getNext(n));
		}
	}else if(isReturnNode(n)){
		printf("Return Node %p with NextNode %p and operation Return", n, getNext(n));
		PrintExpr(getRetExpr(n));
		printf("\n");
		if(visited.find(getNext(n))==visited.end()){
			todo.push_back(getNext(n));
			visited.insert(getNext(n));
		}
	}else if(isCallNode(n)){
		printf("Call Node %p with NextNode %p and operation ", n, getNext(n));
		PrintExpr(getLval(n));
		printf("=");
		printf("%s",getFunName(n));
		printf("(");

		vector<Expr*> ap=getActPara(n);
		for(unsigned j=0;j<ap.size();j++){
			PrintExpr(ap[j]);
			if(j!=ap.size()-1)
				printf(",");
		}
		printf(")\n");
		if(visited.find(getNext(n))==visited.end()){
			todo.push_back(getNext(n));
			visited.insert(getNext(n));
		}
	}else if(isBadNode(n)){
		printf("Found a Bad Node %p\n", n);
	}else{
		printf("Found an Unrecognized Node, parser error! %p\n", n);
		exit(0);
	}
  }
  printf("# of nodes: %d\n", c);
  return 0;
}


